home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 751-760 / 753 / zoo / zoosrc.zoo / portable.c < prev    next >
C/C++ Source or Header  |  1991-07-29  |  21KB  |  726 lines

  1. #ifndef LINT
  2. /* @(#) portable.c 2.24 88/08/24 01:22:06 */
  3. static char sccsid[]="@(#) portable.c 2.24 88/08/24 01:22:06";
  4. #endif /* LINT */
  5.  
  6. #include "options.h"
  7. /*
  8. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  9. (C) Copyright 1988 Rahul Dhesi -- All rights reserved
  10. */
  11. /**********************
  12. portable.c contains functions needed to make Zoo portable to various
  13. implementations of C.
  14.  
  15. Note:  Provided a 2's complement machine is used, all functions in
  16. this file are themselves machine-independent and need not be changed
  17. when implementing Zoo on a different machine.  Some code will choke
  18. on 1's complement machines--I think.
  19.  
  20. For machine-dependent declarations see files "machine.h" and "options.h".
  21.  
  22. For machine-dependent functions see file "machine.c"
  23. */
  24.  
  25. #include "zoo.h"
  26. #include "zooio.h"
  27.  
  28. #include "various.h"
  29. #include "zoofns.h"
  30.  
  31. #include "machine.h"
  32. #include "debug.h"
  33. #include "assert.h"
  34.  
  35. #ifdef NEEDCTYP
  36. #include <ctype.h>                  /* for tolower() */
  37. #endif
  38.  
  39. #include "portable.h"
  40.  
  41. #ifdef TRACE_IO
  42. extern int verbose;
  43. #endif
  44.  
  45. /* Functions defined for use within this file only.  */
  46. long to_long PARMS((BYTE[]));
  47. int to_int PARMS((BYTE[]));
  48. void b_to_zooh PARMS((struct zoo_header *, BYTE[]));
  49. void b_to_dir PARMS((struct direntry *, BYTE[]));
  50. int dir_to_b PARMS((BYTE[], struct direntry *));
  51. void zooh_to_b PARMS((BYTE[], struct zoo_header *));
  52. void splitlong PARMS((BYTE[], long));
  53. void splitint PARMS((BYTE[], int));
  54.  
  55. #ifdef TRACE_IO
  56. void show_h PARMS ((struct zoo_header *));
  57. void show_dir PARMS ((struct direntry *));
  58. #endif /* TRACE_IO */
  59.  
  60. extern unsigned int crccode;
  61.  
  62. /************************************************************************/
  63. /* I/O functions */
  64. /************************************************************************/
  65.  
  66. /* some functions get defined only if they aren't already macros */
  67.  
  68. #ifndef zooread
  69. int zooread (file, buffer, count)
  70. ZOOFILE file; char *buffer; int count;
  71. { return (fread (buffer, 1, count, file)); }
  72. #endif /* zooread */
  73.  
  74. #ifndef FIZ
  75. #ifndef zoowrite
  76. int zoowrite (file, buffer, count)
  77. ZOOFILE file; char *buffer; int count;
  78. {
  79.     if (file == NULLFILE)
  80.         return (count);
  81.     else
  82.         return (fwrite (buffer, 1, count, file));
  83. }
  84. #endif /* zoowrite */
  85.  
  86. ZOOFILE zoocreate (fname)
  87. char *fname;
  88. { return ((ZOOFILE) fopen (fname, Z_NEW)); }
  89.  
  90. #endif /* FIZ */
  91.  
  92. #ifndef zooseek
  93. long zooseek (file, offset, whence)
  94. ZOOFILE file; long offset; int whence;
  95. { return (fseek (file, offset, whence)); }
  96. #endif /* zooseek */
  97.  
  98. ZOOFILE zooopen (fname, option)
  99. char *fname; char *option;
  100. { return ((ZOOFILE) fopen (fname, option)); }
  101.  
  102. #ifndef zootell
  103. long zootell (file)
  104. ZOOFILE file;
  105. { return ftell (file); }
  106. #endif /* zootell */
  107.  
  108. int zooclose (file)
  109. ZOOFILE file;
  110. { return fclose (file); }
  111.  
  112. /**********************
  113. low_ch() is a macro that returns a lowercased char; it may be
  114. used with any char, whether or not it is uppercase.    It will
  115. be used below by one or two functions.
  116. */
  117.  
  118. #define low_ch(c)    (isupper(c) ? tolower(c) : c)
  119. #ifndef toascii
  120. #define toascii(c)   (c)
  121. #endif
  122.  
  123. /************************************************************************/
  124. /*** Following are functions that make up for various implementations ***/
  125. /*** of C not having certain library routines.                                 ***/
  126. /************************************************************************/
  127.  
  128. #ifndef FIZ
  129. /**********************
  130. str_lwr() converts a string to lowercase and returns a pointer to the string
  131. */
  132. char *str_lwr (str)
  133. char *str;
  134. {
  135.     register char *s;
  136.     s = str;
  137.     while (*s != '\0') {
  138.         *s = toascii(*s);
  139.         *s = low_ch(*s);
  140.         s++;
  141.     }
  142.     return (str);
  143. }
  144.  
  145. /**********************
  146. str_icmp() compares strings just like strcmp() but it does it without regard to
  147. case.
  148. */
  149. int str_icmp (s1, s2)
  150. register char *s1, *s2;
  151. {
  152.     for ( ; low_ch(*s1) == low_ch(*s2);  s1++, s2++)
  153.         if (*s1 == '\0')
  154.             return(0);
  155.     return(low_ch(*s1) - low_ch(*s2));
  156. }
  157.  
  158. #ifdef NEED_MEMSET
  159. /**********************
  160. memset() it sets the first "count" bytes of "dest" to the character
  161. "c" and returns a pointer to "dest".
  162. */
  163. char *memset (dest, c, count)
  164. register char *dest;
  165. int c;
  166. unsigned count;
  167. {
  168.     register unsigned i;
  169.     for (i = 0; i < count; i++) {
  170.         *((char *) (dest + i)) = c;
  171.     }
  172.     return dest;
  173. }
  174. #endif /* NEED_MEMSET */
  175.  
  176. #ifdef NEED_MEMCPY
  177. /**********************
  178. memcpy() copies "count" bytes from "src" to "dest" and returns
  179. a pointer to "dest".  Not necessarily safe for overlapping moves. */
  180.  
  181. char *memcpy(dest, src, count)
  182. register char *dest;
  183. register char *src;
  184. unsigned count;
  185. {
  186.     VOIDPTR savedest = dest;
  187.     while (count > 0) {
  188.         *((char *) dest++) = *((char *) src++);
  189.         count--;
  190.     }
  191. }
  192. #endif /* NEED_MEMCPY */
  193.  
  194. #ifndef FPUTCHAR
  195. /**********************
  196. fputchar() writes a character to stdout.  It is identical to putchar
  197. but is a function, not a macro.
  198. */
  199. int fputchar (c)
  200. int c;
  201. {
  202.     return (fputc(c, stdout));
  203. }
  204. #endif /* FPUTCHAR */
  205. #endif /* FIZ */
  206.  
  207. /***********************************************************************/
  208. /*** Following are declarations and functions that are written in a    ***/
  209. /*** machine-independent way but they implement machine-dependent     ***/
  210. /*** activities                                                                        ***/
  211. /***********************************************************************/
  212.  
  213. #ifndef DIRECT_CONVERT
  214. /**********************
  215. to_long() converts four consecutive bytes, in order of increasing
  216. significance, to a long integer.  It is used to make Zoo independent of the
  217. byte order of the system.
  218. */
  219. long to_long(data)
  220. BYTE data[];
  221. {
  222.     return (long) ((unsigned long) data[0] | ((unsigned long) data[1] << 8) |
  223.             ((unsigned long) data[2] << 16) | ((unsigned long) data[3] << 24));
  224. }
  225.  
  226. #ifndef FIZ
  227. /********************
  228. splitlong() converts a long integer to four consecutive BYTEs in order
  229. of increasing significance.
  230. */
  231. void splitlong(bytes, bigword)
  232. BYTE bytes[];
  233. long bigword;
  234. {
  235.     int i;
  236.     for (i = 0; i < 4; i++) {
  237.         bytes[i] = bigword & 0xff;
  238.         bigword = (unsigned long) bigword >> 8;
  239.     }
  240. }
  241. #endif /* FIZ */
  242.  
  243. /*******************
  244. splitint() converts an integer to two consecutive BYTEs in order
  245. of increasing significance.
  246. */
  247. void splitint(bytes, word)
  248. BYTE bytes[];
  249. int word;
  250. {
  251.     bytes[0] = word & 0xff;
  252.     word = (unsigned int) word >> 8;
  253.     bytes[1] = word & 0xff;
  254. }
  255.  
  256. /**********************
  257. to_int() converts two consecutive bytes, in order of increasing
  258. significance, to an integer, in a machine-independent manner
  259. */
  260. int to_int(data)
  261. BYTE data[];
  262. {
  263.     return (int) ((unsigned int) data[0] | ((unsigned int) data[1] << 8));
  264. }
  265.  
  266. #else /* else of ifndef DIRECT_CONVERT */
  267.  
  268. long to_long(data)
  269. BYTE data[];
  270. {
  271.     return ( * (long *) data );
  272. }
  273.  
  274. #ifndef FIZ
  275. /********************
  276. splitlong() converts a long integer to four consecutive BYTEs in order
  277. of increasing significance.
  278. */
  279. void splitlong(bytes, bigword)
  280. BYTE bytes[];
  281. long bigword;
  282. {
  283.     * (long *) bytes = bigword;
  284. }
  285. #endif /* FIZ */
  286.  
  287. /*******************
  288. splitint() converts an integer to two consecutive BYTEs in order
  289. of increasing significance.
  290. */
  291. void splitint(bytes, word)
  292. BYTE bytes[];
  293. int word;
  294. {
  295.     * (int *) bytes = word;
  296. }
  297.  
  298. /**********************
  299. to_int() converts two consecutive bytes, in order of increasing
  300. significance, to an integer.
  301. */
  302. int to_int(data)
  303. BYTE data[];
  304. {
  305.     return (*(int *) data);
  306. }
  307.  
  308. #endif /* ifndef DIRECT_CONVERT .. else ... */
  309.  
  310. #ifndef FIZ
  311. /**********************
  312. Function frd_zooh() reads the header of a Zoo archive in a machine-
  313. independent manner, from a ZOOFILE.
  314. */
  315. int frd_zooh(zoo_header, zoo_file)
  316. struct zoo_header *zoo_header;
  317. ZOOFILE zoo_file;
  318. {
  319.     int status;
  320.     BYTE bytes[SIZ_ZOOH];            /* canonical header representation */
  321. #ifdef TRACE_IO
  322.     if (verbose) {
  323.         printf("At file position [%8lx] ", ftell(zoo_file));
  324.     }
  325. #endif
  326.     status = zooread (zoo_file, (char *) bytes, SIZ_ZOOH);
  327.     b_to_zooh (zoo_header, bytes);   /* convert array to structure */
  328. #ifdef TRACE_IO
  329.     if (verbose) {
  330.         printf("frd_zooh: reading\n");
  331.         show_h(zoo_header);
  332.     }
  333. #endif
  334.     if (status < MINZOOHSIZ)
  335.         return (-1);
  336.     else
  337.         return (0);
  338. }
  339. #endif /* FIZ */
  340.  
  341. /**********************
  342. Function frd_dir() reads a directory entry in a machine-independent manner,
  343. from a ZOOFILE.
  344. */
  345. int frd_dir(direntry, zoo_file)
  346. struct direntry *direntry;
  347. ZOOFILE zoo_file;
  348. {
  349.     int status;
  350.     BYTE bytes[MAXDIRSIZE];     /* big enough to hold variable part too */
  351.  
  352.     /* To simplify things, we read the maximum possible size of the
  353.     directory entry including the variable size and discard what is not
  354.     needed */
  355. #ifdef TRACE_IO
  356.     if (verbose) {
  357.         printf("At file position [%8lx] ", ftell(zoo_file));
  358.     }
  359. #endif
  360.     status = zooread (zoo_file, (char *) bytes, MAXDIRSIZE);
  361.     if (status < SIZ_DIR)
  362.         return (-1);
  363.     b_to_dir (direntry, bytes);
  364. #ifdef TRACE_IO
  365.     if (verbose) {
  366.         printf("frd_dir: reading\n");
  367.         show_dir(direntry);
  368.     }
  369. #endif
  370.     return (0);
  371. }
  372.  
  373. #ifndef FIZ
  374. /***********************
  375. Function fwr_dir() writes a directory entry in a machine-independent manner
  376. to a ZOOFILE.    Return value is -1 on error, else 0.
  377. */
  378. int fwr_dir(direntry, zoo_file)
  379. struct direntry *direntry;
  380. ZOOFILE zoo_file;
  381. {
  382.     int size;
  383.     BYTE bytes[MAXDIRSIZE];
  384.     assert (direntry->type <= 2);
  385.     size = dir_to_b (bytes, direntry);
  386. #ifdef TRACE_IO
  387.     if (verbose) {
  388.         printf("At file position [%8lx] ", ftell(zoo_file));
  389.         printf("fwr_dir: writing\n");
  390.         show_dir(direntry);
  391.     }
  392. #endif
  393.  
  394.     if (zoowrite (zoo_file, (char *) bytes, size) != size)
  395.         return (-1);
  396.     else
  397.         return (0);
  398. }
  399.  
  400. /***********************
  401. Function fwr_zooh() writes an archive header in a machine-independent manner
  402. to a ZOOFILE.    Return value is -1 if error else 0.
  403. */
  404. int fwr_zooh(zoo_header, zoo_file)
  405. struct zoo_header *zoo_header;
  406. ZOOFILE zoo_file;
  407. {
  408.     BYTE bytes[SIZ_ZOOH];    /* was SIZ_DIR -- probably a typo */
  409.     int hsize;                    /* how much to write -- depends on header type */
  410.     hsize = MINZOOHSIZ;                /* in case it's an old type 0 header */
  411.     if (zoo_header->type > 0)     /* but if it's a newer header... */
  412.         hsize = SIZ_ZOOH;             /* ...size of new type 1 header */
  413.     zooh_to_b (bytes, zoo_header);
  414.     if (zoowrite (zoo_file, (char *) bytes, hsize) != hsize)
  415.         return (-1);
  416.     else
  417.         return (0);
  418. }
  419.  
  420. /***********************
  421. b_to_zooh() converts an array of BYTE to a zoo_header structure.
  422. */
  423. void b_to_zooh (zoo_header, bytes)
  424. struct zoo_header *zoo_header;
  425. BYTE bytes[];
  426. {
  427.     int i;
  428.     for (i = 0; i < SIZ_TEXT; i++)                     /* copy text */
  429.         zoo_header->text[i] = bytes[TEXT_I + i];
  430.     zoo_header->zoo_tag = to_long(&bytes[ZTAG_I]);     /* copy zoo_tag */
  431.     zoo_header->zoo_start = to_long(&bytes[ZST_I]);    /* copy zoo_start */
  432.     zoo_header->zoo_minus = to_long(&bytes[ZSTM_I]);
  433.     zoo_header->major_ver = bytes[MAJV_I];             /* copy versions */
  434.     zoo_header->minor_ver = bytes[MINV_I];
  435.     /* default is no archive comment and a header type of 0 */
  436.     zoo_header->type = 0;
  437.     zoo_header->acmt_pos = 0L;
  438.     zoo_header->acmt_len = 0;
  439.     zoo_header->vdata     = 0;
  440.     if (zoo_header->zoo_start != FIXED_OFFSET) {       /* if newer header */
  441.         zoo_header->type = bytes[HTYPE_I];
  442.         zoo_header->acmt_pos = to_long(&bytes[ACMTPOS_I]);
  443.         zoo_header->acmt_len = to_int(&bytes[ACMTLEN_I]);
  444.         zoo_header->vdata     = bytes[HVDATA_I];
  445.     }
  446. }
  447.  
  448. /***********************
  449. zooh_to_b() converts a zoo_header structure to an array of BYTE.
  450. */
  451. void zooh_to_b (bytes, zoo_header)
  452. struct zoo_header *zoo_header;
  453. BYTE bytes[];
  454. {
  455.     int i;
  456.     for (i = 0; i < SIZ_TEXT; i++)                     /* copy text */
  457.         bytes[TEXT_I + i] = zoo_header->text[i];
  458.     splitlong (&bytes[ZTAG_I], zoo_header->zoo_tag);
  459.     splitlong (&bytes[ZST_I], zoo_header->zoo_start);
  460.     splitlong (&bytes[ZSTM_I], zoo_header->zoo_minus);
  461.     bytes[MAJV_I] =    zoo_header->major_ver;                /* copy versions */
  462.     bytes[MINV_I] =    zoo_header->minor_ver;
  463.     bytes[HTYPE_I] =    zoo_header->type;                     /* header type */
  464.     if (zoo_header->type > 0) {
  465.         splitlong (&bytes[ACMTPOS_I], zoo_header->acmt_pos);  /* comment posn */
  466.         splitint (&bytes[ACMTLEN_I], zoo_header->acmt_len);   /* comment len */
  467.         bytes[HVDATA_I] = zoo_header->vdata;                    /* version data */
  468.     }
  469. } /* zooh_to_b() */
  470.  
  471. /************************
  472. dir_to_b() converts a directory entry structure to an array of BYTE.
  473. */
  474. int dir_to_b (bytes, direntry)
  475. struct direntry *direntry;
  476. BYTE bytes[];
  477. {
  478.     int i;
  479.     int cursize;
  480.     int fixsize;
  481.     int totalsize;
  482.     splitlong(&bytes[DTAG_I], direntry->zoo_tag);
  483.     bytes[DTYP_I] = direntry->type ;
  484.     bytes[PKM_I] = direntry->packing_method ;
  485.     splitlong(&bytes[NXT_I], direntry->next);
  486.     splitlong(&bytes[OFS_I], direntry->offset);
  487.     splitint(&bytes[DAT_I], direntry->date);
  488.     splitint(&bytes[TIM_I], direntry->time);
  489.     splitint(&bytes[CRC_I], direntry->file_crc);
  490.     splitlong(&bytes[ORGS_I], direntry->org_size);
  491.     splitlong(&bytes[SIZNOW_I], direntry->size_now);
  492.     bytes[DMAJ_I] = direntry->major_ver;
  493.     bytes[DMIN_I] = direntry->minor_ver;
  494.     bytes[DEL_I] = direntry->deleted;
  495.     bytes[STRUC_I] = direntry->struc;
  496.     splitlong(&bytes[CMT_I], direntry->comment);
  497.     splitint(&bytes[CMTSIZ_I], direntry->cmt_size);
  498.     for (i = 0; i < FNM_SIZ; i++)
  499.         bytes[FNAME_I + i] = direntry->fname[i];
  500.     bytes[TZ_I] = NO_TZ;         /* assume unknown */
  501.     bytes[NAMLEN_I] = 0;
  502.     bytes[DIRLEN_I] = 0;
  503.  
  504.     cursize = SIZ_DIR;            /* to count size of directory */
  505.     fixsize = SIZ_DIR;            /* size of fixed part */
  506.     assert (direntry->type <= 2);
  507.     if (direntry->type == 2) { /* handle stuff relevant to type 2 */
  508.         cursize = SIZ_DIRL;
  509.         fixsize = SIZ_DIRL;
  510.         bytes[TZ_I] = direntry->tz;
  511.         assert(direntry->namlen < 256 && direntry->namlen >= 0);
  512.         cursize += 2;            /* space for namlen and dirlen */
  513.         if (direntry->namlen != 0) {
  514.             bytes[NAMLEN_I] = direntry->namlen;
  515.             for (i = 0; i < direntry->namlen; i++)
  516.                 bytes[LFNAME_I+i] = direntry->lfname[i];
  517.             cursize += direntry->namlen;
  518.         }
  519.         assert(direntry->dirlen < 256 && direntry->dirlen >= 0);
  520.         if (direntry->dirlen != 0) {
  521.             bytes[DIRLEN_I] = direntry->dirlen;
  522.             for (i = 0; i < direntry->dirlen; i++)
  523.                 bytes[cursize+i] = direntry->dirname[i];
  524.             cursize += direntry->dirlen;
  525.         }
  526.         /* Can't store system id if no namlen & dirlen...BUG!...now fixed.
  527.             Fortunately, system_id was always 0 so far so it probably
  528.             got interpreted as namlen=0 and dirlen=0 (2 bytes) */
  529.         splitint(&bytes[cursize], direntry->system_id);
  530.         cursize += 2;
  531.         bytes[cursize] = direntry->fattr & 0xff;                            /* byte 0 */
  532.         splitint(&bytes[cursize+1], (int) (direntry->fattr >> 8));  /* 1 & 2 */
  533.         cursize += 3;
  534.         bytes[cursize] = (direntry->vflag & 0xff);         /* version flag */
  535.         splitint(&bytes[cursize+1], direntry->version_no); /* version number */
  536.         cursize += 3;
  537.     }
  538.  
  539.     splitint(&bytes[VARDIRLEN_I], direntry->var_dir_len);
  540.     assert(cursize ==
  541.                 ((bytes[DIRLEN_I] > 0 || bytes[NAMLEN_I] > 0) ? 2 : 0) +
  542.                 fixsize + bytes[DIRLEN_I] + bytes[NAMLEN_I]
  543.             );
  544.  
  545.     /* total size of dir entry is size of fixed part + size of var. part */
  546.     totalsize = fixsize + direntry->var_dir_len;
  547.  
  548.     /* Do CRC assuming CRC field is zero, and stuff CRC into field. */
  549.     splitint(&bytes[DCRC_I], 0);           /* fill with zeroes */
  550.     crccode = 0;
  551.     /* avoid mixing pointers to signed and unsigned char */
  552.     addbfcrc((char *) bytes, totalsize);      /* update CRC */
  553.     splitint(&bytes[DCRC_I], crccode);
  554.  
  555.     /* return total length of directory entry */
  556.     return (totalsize);
  557.  
  558. } /* dir_to_b() */
  559. #endif /* FIZ */
  560.  
  561. /* b_to_dir() converts bytes to directory entry structure.  The CRC of the
  562. directory bytes, if any, is checked and a zero or nonzero value is returned
  563. in direntry->dir_crc according as the check is good or bad */
  564.  
  565. void b_to_dir(direntry, bytes)
  566. struct direntry *direntry;
  567. BYTE bytes[];
  568. {
  569.     int i;
  570.     int sysid_offs;            /* temp variable */
  571.     unsigned int savecrc;
  572.     direntry->zoo_tag = to_long(&bytes[DTAG_I]);
  573.     direntry->type = bytes[DTYP_I];
  574.     direntry->packing_method = bytes[PKM_I];
  575.     direntry->next = to_long(&bytes[NXT_I]);
  576.     direntry->offset = to_long(&bytes[OFS_I]);
  577.     direntry->date = to_int(&bytes[DAT_I]);
  578.     direntry->time = to_int(&bytes[TIM_I]);
  579.     direntry->file_crc = to_int(&bytes[CRC_I]);
  580.     direntry->org_size = to_long(&bytes[ORGS_I]);
  581.     direntry->size_now = to_long(&bytes[SIZNOW_I]);
  582.     direntry->major_ver = bytes[DMAJ_I];
  583.     direntry->minor_ver = bytes[DMIN_I];
  584.     direntry->deleted = bytes[DEL_I];
  585.     direntry->struc = bytes[STRUC_I];
  586.     direntry->comment = to_long(&bytes[CMT_I]);
  587.     direntry->cmt_size = to_int(&bytes[CMTSIZ_I]);
  588.     /* for now, versions not implemented */
  589.     direntry->vflag = 0;
  590.     direntry->version_no = 0;
  591.     for (i = 0; i < FNM_SIZ; i++)
  592.         direntry->fname[i] = bytes[FNAME_I + i];
  593.  
  594.     /* start by assuming variable part is zero bytes */
  595.     direntry->var_dir_len = direntry->dir_crc     = 0;
  596.     direntry->namlen         = direntry->dirlen        = 0;
  597.     direntry->lfname[0]     = direntry->dirname[0] = '\0';
  598.     direntry->tz = NO_TZ;                    /* assume unknown */
  599.     direntry->system_id = SYSID_NIX;     /* default system_id if not present */
  600.     direntry->fattr = NO_FATTR;            /* assume none */
  601.  
  602.     assert (direntry->type <= 2);
  603.     if (direntry->type == 2) {
  604.         direntry->var_dir_len = to_int(&bytes[VARDIRLEN_I]);
  605.         assert(direntry->var_dir_len <= MAXDIRSIZE);
  606.         if (direntry->var_dir_len > MAXDIRSIZE)
  607.             direntry->var_dir_len = MAXDIRSIZE;
  608.         direntry->tz = bytes[TZ_I];
  609.         if (direntry->var_dir_len > 0)
  610.             direntry->namlen = bytes[NAMLEN_I];
  611.         if (direntry->var_dir_len > 1)
  612.             direntry->dirlen = bytes[DIRLEN_I];
  613.         for (i = 0; i < direntry->namlen; i++)
  614.             direntry->lfname[i] = bytes[LFNAME_I + i];
  615.         for (i = 0; i < direntry->dirlen; i++)
  616.             direntry->dirname[i] = bytes[DIRNAME_I + direntry->namlen + i];
  617.         sysid_offs = DIRNAME_I + direntry->namlen + i;    /* offset of system id */
  618.         if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 2) {
  619.             direntry->system_id = to_int(&bytes[sysid_offs]);
  620.         }
  621.         if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 4) {
  622.             direntry->fattr = ((unsigned long) bytes[sysid_offs + 2]) |
  623.                                     ((unsigned long) bytes[sysid_offs + 3] << 8) |
  624.                                     ((unsigned long) bytes[sysid_offs + 4] << 16);
  625.         }
  626.         if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 7) {
  627.             direntry->vflag = bytes[sysid_offs + 5];
  628.             direntry->version_no = to_int(&bytes[sysid_offs + 6]);
  629.         }
  630.         /* do CRC calculation */
  631.         savecrc = (unsigned int) to_int(&bytes[DCRC_I]);
  632.         crccode = 0;
  633.         splitint(&bytes[DCRC_I], 0);
  634.         addbfcrc((char *) bytes, SIZ_DIRL + direntry->var_dir_len);
  635.         direntry->dir_crc = crccode - savecrc;
  636.     }
  637. }
  638.  
  639. #ifdef FILTER
  640. #define TWOBYTES    2    /* better than literal 2;    figure out why */
  641.  
  642. /* rdint() reads two bytes from standard input in archive order */
  643. int rdint (val)
  644. unsigned int *val;
  645. {
  646.     BYTE bytes[TWOBYTES];
  647.     if (zooread (STDIN, bytes, TWOBYTES) == TWOBYTES) {
  648.         *val = to_int(bytes);
  649.         return (0);
  650.     } else
  651.         return (1);
  652. }
  653.  
  654. /* wrint() writes an unsigned int to standard output in archive order */
  655. int wrint (val)
  656. unsigned int val;
  657. {
  658.     BYTE bytes[TWOBYTES];
  659.     splitint (bytes, val);
  660.     if (zoowrite (STDOUT, bytes, TWOBYTES) == TWOBYTES)
  661.         return (0);
  662.     else
  663.         return (1);
  664. }
  665. #endif /* FILTER */
  666.  
  667. #ifdef TRACE_IO
  668. /* dump contents of archive header */
  669. void show_h (zoo_header)
  670. struct zoo_header *zoo_header;
  671. {
  672.     int i;
  673.     printf ("Header text:\n");
  674.     for (i = 0; i < SIZ_TEXT;  i++) {      /* ASSUMES ASCII TEXT */
  675.         int c;
  676.         c = zoo_header->text[i];
  677.         if (c >= ' ' && c < 0x7f)
  678.             putchar (c);
  679.         else {
  680.             putchar ('^');
  681.             putchar (i & 0x40);
  682.         }
  683.     }
  684.     putchar('\n');
  685.     printf ("zoo_tag = [%8lx] zoo_start = [%8lx] zoo_minus = [%8lx]\n",
  686.                 zoo_header->zoo_tag, zoo_header->zoo_start,
  687.                 zoo_header->zoo_minus);
  688.     printf ("major_ver.minor_ver = [%d.%d]\n",
  689.                 zoo_header->major_ver, zoo_header->minor_ver);
  690.     if (zoo_header->zoo_start != FIXED_OFFSET) {
  691.         printf ("type = [%d] ", zoo_header->type);
  692.         printf ("acmt_pos = [%8lx] acmt_len = [%4x] vdata = [%2x]",
  693.                     zoo_header->acmt_pos, zoo_header->acmt_len, zoo_header->vdata);
  694.         printf ("\n");
  695.     }
  696.     printf ("---------\n");
  697. }
  698.  
  699. /* dump contents of directory entry */
  700. void show_dir (direntry)
  701. struct direntry *direntry;
  702. {
  703.     printf ("Directory entry for file [%s][%s]:\n",
  704.                 direntry->fname, direntry->lfname);
  705.     printf ("tag = [%8lx] type = [%d] PM = [%d] Next = [%8lx] Offset = [%8lx]\n",
  706.                 direntry->zoo_tag, (int) direntry->type,
  707.                 (int) direntry->packing_method, direntry->next,
  708.                 direntry->offset);
  709.     printf ("Orig size = [%ld] Size now = [%ld] dmaj_v.dmin_v = [%d.%d]\n",
  710.             direntry->org_size, direntry->size_now,
  711.             (int) direntry->major_ver, (int) direntry->minor_ver);
  712.     printf ("Struc = [%d] DEL = [%d] comment_offset = [%8lx] cmt_size = [%d]\n",
  713.             (int) direntry->struc, (int) direntry->deleted, direntry->comment,
  714.             direntry->cmt_size);
  715.     printf ("var_dir_len = [%d] TZ = [%d] dir_crc = [%4x]\n",
  716.                 direntry->var_dir_len, (int) direntry->tz, direntry->dir_crc);
  717.     printf ("system_id = [%d]  dirlen = [%d]  namlen = [%d] fattr=[%24lx]\n",
  718.         direntry->system_id, direntry->dirlen, direntry->namlen, direntry->fattr);
  719.     printf ("vflag = [%4x] version_no = [%4x]\n",
  720.                 direntry->vflag, direntry->version_no);
  721.     if (direntry->dirlen > 0)
  722.         printf ("dirname = [%s]\n", direntry->dirname);
  723.     printf ("---------\n");
  724. }
  725. #endif    /* TRACE_IO */
  726.